package com.exe.base;


import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import com.exe.base.annotation.DyMethod;
import com.exe.base.annotation.DyParam;
import com.exe.base.annotation.DyParams;
import com.exe.base.vo.CmdVo;
import kkd.common.util.StringUtil;


public abstract class Cmd {
	
	protected CmdHandle cmdHandle;
	protected static Map<String,DyMethod> methodMap=null;
	
	public String opName;//命令
	public abstract String op();//命令

	public void init(){
		if(methodMap==null){
			methodMap=new HashMap<>();
			Method[] methods=this.getClass().getDeclaredMethods();
			for(Method method:methods){
				if(method.isAnnotationPresent(DyMethod.class)){
					DyMethod[] dyMethods=method.getAnnotationsByType(DyMethod.class);
					if(dyMethods!=null){
						for(DyMethod dyMethod:dyMethods){
							methodMap.put(dyMethod.value(),dyMethod);
						}
					}
				}
			}
		}
	}

	public void exe(CmdVo caiAction, Map<String, String> param) {
		init();
		String methodStr=param.get("sys.method");
		String returnKey=param.get("sys.return");
		if(StringUtil.isEmpty(methodStr)){
			return;
		}
		DyMethod dyMethod=methodMap.get(methodStr);
		DyParams dyParams=dyMethod.params();
		DyParam[] dyParamList=dyParams.value();
		Class[] argTypes=new Class[dyParamList.length];
		Object[] args=new Object[dyParamList.length];
		for(int i=0;i<dyParamList.length;i++){
			DyParam dyParam=dyParamList[i];
			String paramName=dyParam.value();
			String dataType=dyParam.dataType();
			Class c=getType(dataType);
			argTypes[i]=c;
			//@ 前缀的表示引用变量
			if(param.keySet().contains("ref."+paramName)){
				args[i]=cmdHandle.getVars().get(paramName);
			}else{
				args[i]=param.get(paramName);
			}
		}
		try {
			Method method=this.getClass().getMethod(methodStr,argTypes);
			Object rs=method.invoke(this,args);
			cmdHandle.getVars().put(returnKey,rs);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void clear(){
		methodMap=null;
	}

	public static Class getType(String type){
		if("STRING".equalsIgnoreCase(type)){
			return String.class;
		}else if("LONG".equalsIgnoreCase(type)){
			return Long.class;
		}else if("INT".equalsIgnoreCase(type)){
			return Integer.class;
		}else if("INTEGER".equalsIgnoreCase(type)){
			return Integer.class;
		}else if("boolean".equalsIgnoreCase(type)){
			return Boolean.class;
		}else {
			return String.class;
		}

	}

}
